package com.zj.project.common.base

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

/**
 * createTime:2021/7/26 15:35
 * auth:张继
 * des:
 */
abstract class BaseFragment<VDB : ViewDataBinding, VM : BaseViewModel> : Fragment(), IBaseView<VM> {
    protected lateinit var binding: VDB
    protected val viewModel: VM by lazy {
        createViewModel()
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(inflater, layoutId(), container, false)
        binding.setVariable(variableId(), viewModel)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initData(savedInstanceState)
    }

    override fun createViewModel(): VM {
        return obtainViewModel(getVMClass())
    }

    private fun getVMClass(): Class<VM> {
        var javaClass: Class<*> = javaClass
        var vmClass: Class<VM>? = null
        while (vmClass == null && javaClass != null) {
            vmClass = getVMClass(javaClass)
            javaClass = javaClass.superclass
        }
        if (vmClass == null) {
            vmClass = BaseViewModel::class.java as Class<VM>
        }
        return vmClass
    }

    private fun getVMClass(cls: Class<*>): Class<VM>? {
        val type = cls.genericSuperclass
        if (type is ParameterizedType) {
            val types: Array<Type> = type.actualTypeArguments
            types.forEach {
                if (it is Class<*>) {
                    if (BaseViewModel::class.java.isAssignableFrom(it)) {
                        return it as Class<VM>
                    }
                } else if (it is ParameterizedType) {
                    val rawType: Type = it.rawType
                    if (rawType is Class<*>) {
                        if (BaseViewModel::class.java.isAssignableFrom(rawType)) {
                            return rawType as Class<VM>
                        }
                    }
                }
            }
        }
        return null
    }

    private fun obtainViewModel(vmClass: Class<VM>): VM {
        return createViewModelProvider().get(vmClass)
    }

    private fun createViewModelProvider() = ViewModelProvider(
        this,
        ViewModelProvider.AndroidViewModelFactory(requireActivity().application)
    )


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycle.addObserver(viewModel)
    }


    override fun isTranslucent(): Boolean {
        return true
    }

    override fun onDestroy() {
        lifecycle.removeObserver(viewModel)
        binding.unbind()
        super.onDestroy()
    }
}